package com.finalterm.product.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.finalterm.common.result.Result;
import com.finalterm.product.feign.UserServiceClient;
import com.finalterm.product.service.ProductCacheService;
import com.finalterm.product.vo.ProductVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

/**
 * 熔断测试控制器
 * 用于测试Sentinel熔断功能
 */
@Slf4j
@RestController
@RequestMapping("/api/product/test")
@RequiredArgsConstructor
public class CircuitBreakerTestController {
    
    private final UserServiceClient userServiceClient;
    private final ProductCacheService productCacheService;
    
    /**
     * 测试用户服务调用（正常）
     */
    @GetMapping("/user/validate/{userId}")
    @SentinelResource(value = "test-user-validate", fallback = "testUserValidateFallback")
    public Result<String> testUserValidate(@PathVariable Long userId) {
        try {
            Result<Boolean> result = userServiceClient.validateUser(userId);
            if (result.getCode() == 200 && result.getData() != null && result.getData()) {
                return Result.success("用户验证成功");
            } else {
                return Result.error("用户验证失败");
            }
        } catch (Exception e) {
            log.error("用户服务调用异常: {}", e.getMessage());
            throw e; // 重新抛出异常，让Sentinel感知到失败
        }
    }
    
    /**
     * 测试用户服务调用降级方法
     */
    public Result<String> testUserValidateFallback(Long userId, Throwable ex) {
        log.warn("用户服务调用熔断降级，userId: {}, 异常: {}", userId, ex.getMessage());
        return Result.success("用户服务熔断，执行降级逻辑");
    }
    
    /**
     * 测试获取默认商品缓存
     */
    @GetMapping("/cache/product/{productId}")
    public Result<ProductVO> testGetCachedProduct(@PathVariable Long productId) {
        ProductVO cachedProduct = productCacheService.getDefaultProduct(productId);
        return Result.success("获取缓存商品成功", cachedProduct);
    }
    
    /**
     * 测试添加默认商品缓存
     */
    @PostMapping("/cache/product/{productId}")
    public Result<String> testAddCachedProduct(@PathVariable Long productId, 
                                             @RequestParam String name,
                                             @RequestParam(required = false, defaultValue = "99.00") String price) {
        ProductVO productVO = new ProductVO();
        productVO.setId(productId);
        productVO.setName(name + "（测试缓存）");
        productVO.setDescription("这是一个测试缓存商品");
        productVO.setPrice(new java.math.BigDecimal(price));
        productVO.setStock(0);
        productVO.setCategory("测试分类");
        productVO.setImageUrl("/images/test-product.jpg");
        productVO.setStatus(1);
        productVO.setCreateTime(java.time.LocalDateTime.now());
        productVO.setUpdateTime(java.time.LocalDateTime.now());
        
        productCacheService.putDefaultProduct(productId, productVO);
        return Result.success("添加缓存商品成功");
    }
    
    /**
     * 测试清除商品缓存
     */
    @DeleteMapping("/cache/product/{productId}")
    public Result<String> testRemoveCachedProduct(@PathVariable Long productId) {
        productCacheService.removeDefaultProduct(productId);
        return Result.success("清除缓存商品成功");
    }
    
    /**
     * 获取缓存统计信息
     */
    @GetMapping("/cache/stats")
    public Result<String> testGetCacheStats() {
        int cacheSize = productCacheService.getCacheSize();
        return Result.success("当前缓存商品数量: " + cacheSize);
    }
    
    /**
     * 模拟高并发调用用户服务（用于触发熔断）
     */
    @GetMapping("/stress/user/{userId}")
    @SentinelResource(value = "stress-test-user", fallback = "stressTestFallback")
    public Result<String> stressTestUserService(@PathVariable Long userId,
                                              @RequestParam(defaultValue = "10") int count) {
        log.info("开始压力测试，调用次数: {}", count);
        
        int successCount = 0;
        int failCount = 0;
        
        for (int i = 0; i < count; i++) {
            try {
                Result<Boolean> result = userServiceClient.validateUser(userId);
                if (result.getCode() == 200) {
                    successCount++;
                } else {
                    failCount++;
                }
            } catch (Exception e) {
                failCount++;
                log.warn("第{}次调用失败: {}", i + 1, e.getMessage());
            }
            
            // 短暂延迟
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            }
        }
        
        return Result.success(String.format("压力测试完成，成功: %d, 失败: %d", successCount, failCount));
    }
    
    /**
     * 压力测试降级方法
     */
    public Result<String> stressTestFallback(Long userId, int count, Throwable ex) {
        log.warn("压力测试熔断降级，userId: {}, count: {}, 异常: {}", userId, count, ex.getMessage());
        return Result.success("压力测试触发熔断，执行降级逻辑");
    }
}
